class DiaMarcacion
  attr_accessor :usuario,:fecha,:marcaciones,:marcar_salida,
    :llegadas_tardias,:salidas_prematuras,:carga_horaria,
    :horarios,:autorizacion,:autorizaciones
  
  def initialize (usuario,fecha,args={})
    @fecha=fecha
    @marcaciones_texto=''
    @usuario=usuario
    @horarios=[]
    @marcar_salida=true
    @carga_horaria=0
    @llegadas_tardias=[]
    @salidas_prematuras=[]
    @marcaciones= args[:marcaciones] || @usuario.marcaciones.por_fecha(fecha)
    @incompleta=(@marcaciones.count%2==0) ? false : true
    #return if @marcaciones.blank?
    @plan_horario=args[:plan_horario] || @usuario.planes_horarios.por_fecha(fecha).first#.find(:first,:include=>[:grupo_horario,:horarios])
    if @plan_horario
      @tolerancia_tardias= args[:tolerancia_tardias] || Parametro.find_by_codigo('PV01').try(:valor).to_i
      @autorizaciones= args[:autorizaciones] || self.usuario.autorizaciones.por_mes(self.fecha).group_by(&:fecha)
      args[:grupo_horario]||=@plan_horario.grupo_horario
      @horarios=traer_horarios_del_dia(args[:grupo_horario])
      @marcar_salida=args[:grupo_horario].controla_salida
      @carga_horaria=args[:grupo_horario].carga
      @incompleta=true if (@marcaciones.count<@horarios.count*2)
      (@incompleta=false) if !@marcar_salida
      unless (@incompleta or !@marcar_salida)
        begin
          @llegadas_tardias= traer_llegadas_tardias
          @salidas_prematuras= traer_salidas_prematuras
        rescue
          puts "ERROR"
        end
      end
    end
  end

  def irregular?(ignorar_si_cumplio_carga_horaria=false)
    result=((!self.marcaciones.blank? and !self.horarios.blank?) and (self.incompleta? or !self.llegadas_tardias.blank? or !self.salidas_prematuras.blank?))
    result=false if self.cumple_carga_horaria? and ignorar_si_cumplio_carga_horaria
    result
  end
  
  def autorizacion
    @autorizacion||= self.autorizaciones[self.fecha].try(:first).try(:usuario_id)==self.usuario.id ? self.autorizaciones[self.fecha] : nil
  end
  
  def domingo?
    @fecha.cwday==7
  end

  def feriado?
    @feriado||=!Feriado.find_by_fecha(@fecha.day,@fecha.month).find_by_sucursal_id(@usuario.sucursal_id).blank?
  end

  def incompleta?
    @incompleta
  end

  def horas_trabajadas
    @horas_trabajadas||= calcular_horas_trabajadas
  end

  def horas_trabajadas_en_minutos
    self.horas_trabajadas*60
  end

  def marcaciones_texto
    if @marcaciones_texto.blank?
      @marcaciones_texto+="(Domingo) " if domingo?
      @marcaciones_texto+="(Feriado) " if feriado?
      @marcaciones_texto+=@marcaciones.map{|m| I18n.l(m.hora,:format=>:time)}.join(" - ")
    end
    @marcaciones_texto
  end

  def cumple_carga_horaria?
    horas_trabajadas >= carga_horaria_del_dia
  end

  #Se agregó este método ya que existe la posibilidad de que el valor del campo 'carga'
  #de la tabla 'grupos_horarios', no se cumpla, ejemplo: los sábados
  def carga_horaria_del_dia
    #@fecha.wday == 6 ? carga_horaria_sabado : @carga_horaria
    ht=0
    @horarios.each {|h| (ht+=(h.fin-h.inicio)/3600)}
    sprintf("%.3f",ht).to_f    
  end

  def carga_horaria_sabado
    ht=0
    @horarios.each {|h| (ht+=(h.fin-h.inicio)/3600)}
    sprintf("%.3f",ht).to_f
  end

  def carga_horaria_del_dia_en_minutos
    carga_horaria_del_dia*60
  end

  private
  def calcular_horas_trabajadas
    ht=0
    if @marcar_salida
    (0..(@marcaciones.length-1)).step(2) {|i| (ht+=(@marcaciones[i+1].hora-@marcaciones[i].hora)/3600)} unless @marcaciones.count%2!=0
    else
    end
    sprintf("%.3f",ht).to_f
  end

  #Trae los horarios correspondientes al dia de la marcacion
  def traer_horarios_del_dia(grupo_horario=nil)
    grupo_horario= grupo_horario || @plan_horario.grupo_horario
    dia=I18n.l(@fecha,:format=>:day_name).downcase
    dia.gsub!('é','e') if dia.include?('é')
    dia.gsub!('á','a') if dia.include?('á')
    grupo_horario.horarios.collect{|h| h if h.send(dia)}.compact
  end

  def traer_llegadas_tardias
    marcaciones_de_tipo('t')
  end

  def traer_salidas_prematuras
    marcaciones_de_tipo('p')
  end

  def marcaciones_de_tipo(tipo)
    conf= {:desde=>1,:metodo=>"fin",:tolerancia=>0,:comp=>"<=",:val => "-1.0" }
    if tipo=='t'
      conf={:desde=>0,:metodo=>"inicio",:tolerancia=>@tolerancia_tardias,:comp=>">=",:val => "1.0"}
    end
    result=[]
    @horarios.each do |h|
      horario=h.send(conf[:metodo]).advance(:minutes=>conf[:tolerancia]).to_f
      marcacion=@marcaciones[conf[:desde]].hora.to_f
      result<<@marcaciones[conf[:desde]] if eval("#{(marcacion-horario)/60}#{conf[:comp]}#{conf[:val]}")
      conf[:desde]+=2
    end
    result
  end
  
end